package com.unibuy.smartdevice.ui.tools;

import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;

import androidx.annotation.OptIn;
import androidx.media3.common.MediaItem;
import androidx.media3.common.PlaybackException;
import androidx.media3.common.Player;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.datasource.DefaultDataSource;
import androidx.media3.exoplayer.DefaultLoadControl;
import androidx.media3.exoplayer.DefaultRenderersFactory;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.source.MediaSource;
import androidx.media3.exoplayer.source.ProgressiveMediaSource;
import androidx.media3.extractor.DefaultExtractorsFactory;
import androidx.media3.ui.PlayerView;

import com.unibuy.smartdevice.MyApp;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.exception.LogsEmptyException;
import com.unibuy.smartdevice.exception.LogsFileNullException;
import com.unibuy.smartdevice.exception.LogsIOException;
import com.unibuy.smartdevice.exception.LogsMalformedURLException;
import com.unibuy.smartdevice.tools.HttpConnect;

import java.io.File;

public class VideoEoxPlayer {
    private final Logs logs;
    private final Context context;
    private ExoPlayer exoPlayer;
    private PlayerView currentPlayerView;
    private static int exoPlayerTotal;

    public static int getExoPlayerTotal() {
        return exoPlayerTotal;
    }

    public static void setExoPlayerTotal(int exoPlayerTotal) {
        VideoEoxPlayer.exoPlayerTotal = exoPlayerTotal;
    }

    public VideoEoxPlayer(Context context) {
        this.context = context;
        this.logs = new Logs(getClass());
    }

    private MediaItem fileload(String urlString) throws LogsEmptyException, LogsFileNullException {
        HttpConnect httpConnect = new HttpConnect();
        File videoFile = httpConnect.getFileFromUrl(urlString);
        Uri videoUri = videoFile.exists() ? Uri.fromFile(videoFile) : Uri.parse(urlString);
        return MediaItem.fromUri(videoUri);
    }

    @OptIn(markerClass = UnstableApi.class)
    public void videoPlay(PlayerView videoView, int field) throws LogsFileNullException, LogsEmptyException {
        if (MyApp.getInstance().getFontendAdUrlString().isEmpty()) return;

        if (exoPlayer != null) {
            videoStop();
        }

        logs.info("[VideoEoxPlayer] Initializing ExoPlayer...");

        DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(context)
                .setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER)
                .setEnableDecoderFallback(true);

        DefaultLoadControl loadControl = new DefaultLoadControl.Builder()
                .setBufferDurationsMs(5000, 100000, 3000, 5000)
                .build();

        exoPlayer = new ExoPlayer.Builder(context)
                .setRenderersFactory(renderersFactory)
                .setLoadControl(loadControl)
                .build();

        if (currentPlayerView != null) {
            currentPlayerView.setPlayer(null);
        }

        currentPlayerView = videoView;
        currentPlayerView.setPlayer(exoPlayer);
        logs.info("[VideoEoxPlayer] PlayerView set successfully.");

        DefaultExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
        ProgressiveMediaSource.Factory mediaSourceFactory = new ProgressiveMediaSource.Factory(
                new DefaultDataSource.Factory(context), extractorsFactory
        );

        setExoPlayerTotal(MyApp.getInstance().getFontendAdUrlString().size());

        for (String urlString : MyApp.getInstance().getFontendAdUrlString()) {
            MediaItem mediaItem = fileload(urlString);
            MediaSource mediaSource = mediaSourceFactory.createMediaSource(mediaItem);
            exoPlayer.addMediaSource(mediaSource);
        }

        exoPlayer.setRepeatMode(Player.REPEAT_MODE_OFF);

        exoPlayer.addListener(new Player.Listener() {
            @Override
            public void onPlayerError(PlaybackException error) {
                if (exoPlayer != null) {
                    logs.debug("[VideoEoxPlayer] Playback error: " + error.getLocalizedMessage());
                    if (exoPlayer.hasNextMediaItem()) {
                        exoPlayer.seekToNext();
                    } else {
                        exoPlayer.seekTo(0, 0);
                    }
                    exoPlayer.prepare();
                    exoPlayer.setPlayWhenReady(true);
                }
            }

            @Override
            public void onPlaybackStateChanged(int state) {
                if (exoPlayer == null) return;

                MediaItem currentItem = exoPlayer.getCurrentMediaItem();
                if (currentItem == null || currentItem.localConfiguration == null) return;

                String mediaUri = currentItem.localConfiguration.uri.toString();
                boolean isImage = mediaUri.endsWith(".png") || mediaUri.endsWith(".jpg") || mediaUri.endsWith(".gif");

                int nextIndex = exoPlayer.getCurrentMediaItemIndex() + 1;
                boolean hasNext = nextIndex < exoPlayer.getMediaItemCount();
                boolean nextIsImage = false;

                if (hasNext) {
                    MediaItem nextItem = exoPlayer.getMediaItemAt(nextIndex);
                    if (nextItem != null && nextItem.localConfiguration != null) {
                        String nextMediaUri = nextItem.localConfiguration.uri.toString();
                        nextIsImage = nextMediaUri.endsWith(".png") || nextMediaUri.endsWith(".jpg") || nextMediaUri.endsWith(".gif");
                    }
                }

                logs.info("state:" + state + " isImage:" + isImage + " nextIsImage:" + nextIsImage + " mediaUri:" + mediaUri);

                if (state == Player.STATE_READY) {
                    if (isImage) {
                        exoPlayer.stop();
                        new Handler(Looper.getMainLooper()).postDelayed(() -> {
                            if (exoPlayer != null) {
                                if (exoPlayer.hasNextMediaItem()) {
                                    exoPlayer.seekToNext();
                                } else {
                                    exoPlayer.seekTo(0, 0);
                                }
                                exoPlayer.prepare();
                                exoPlayer.setPlayWhenReady(true);
                            }
                        }, 15000);
                    }
                }

                if (state == Player.STATE_ENDED) {
                    if (isImage) {
                        exoPlayer.stop();
                        new Handler(Looper.getMainLooper()).postDelayed(() -> {
                            if (exoPlayer != null) {
                                if (exoPlayer.hasNextMediaItem()) {
                                    exoPlayer.seekToNext();
                                } else {
                                    exoPlayer.seekTo(0, 0);
                                }
                                exoPlayer.prepare();
                                exoPlayer.setPlayWhenReady(true);
                            }
                        }, 15000);
                    } else {
                        if (exoPlayer != null) {
                            if (exoPlayer.hasNextMediaItem()) {
                                exoPlayer.seekToNext();
                            } else {
                                exoPlayer.seekTo(0, 0);
                            }
                            exoPlayer.prepare();
                            exoPlayer.setPlayWhenReady(true);
                        }
                    }
                }
            }
        });

        exoPlayer.prepare();
        exoPlayer.setPlayWhenReady(true);
    }

    public void videoStop() {
        if (exoPlayer != null) {
            logs.info("[VideoEoxPlayer] Stopping and releasing ExoPlayer...");
            exoPlayer.stop();
            exoPlayer.release();
            exoPlayer = null;

            if (currentPlayerView != null) {
                currentPlayerView.setPlayer(null);
                currentPlayerView = null;
            }
        }
    }

    public void preload(String urlString) throws LogsEmptyException, LogsFileNullException, LogsMalformedURLException, LogsIOException {
        logs.info("Preloading video: " + urlString);
        HttpConnect httpConnect = new HttpConnect();
        File videoFile = httpConnect.download(urlString, true);
        logs.info("Preloaded file: " + videoFile.getAbsolutePath());
    }
}
